from typing import List, Dict, Any, Generic, TypeVar, Optional
from flask import request

T = TypeVar('T')

class Pagination(Generic[T]):
    """
    分页工具类
    """
    def __init__(self,
                 items: List[T],
                 page: int,
                 per_page: int,
                 total: int,
                 base_url: Optional[str] = None,
                 **kwargs):
        self.items = items  # 当前页的项目列表
        self.page = page  # 当前页码
        self.per_page = per_page  # 每页显示数量
        self.total = total  # 总项目数
        self.base_url = base_url or request.path  # 基础URL
        self.kwargs = kwargs  # 额外参数
    
    @property
    def pages(self) -> int:
        """
        总页数
        """
        if self.per_page == 0:
            return 0
        return (self.total + self.per_page - 1) // self.per_page
    
    @property
    def has_prev(self) -> bool:
        """
        是否有上一页
        """
        return self.page > 1
    
    @property
    def prev_num(self) -> Optional[int]:
        """
        上一页页码
        """
        return self.page - 1 if self.has_prev else None
    
    @property
    def has_next(self) -> bool:
        """
        是否有下一页
        """
        return self.page < self.pages
    
    @property
    def next_num(self) -> Optional[int]:
        """
        下一页页码
        """
        return self.page + 1 if self.has_next else None
    
    def to_dict(self, items_converter=lambda x: x) -> Dict[str, Any]:
        """
        转换为字典格式返回
        
        Args:
            items_converter: 项目转换函数，用于将每个项目转换为适当的格式
            
        Returns:
            包含分页信息的字典
        """
        return {
            'items': [items_converter(item) for item in self.items],
            'total': self.total,
            'page': self.page,
            'per_page': self.per_page,
            'pages': self.pages,
            'has_prev': self.has_prev,
            'has_next': self.has_next,
            'prev_num': self.prev_num,
            'next_num': self.next_num
        }
    
    @classmethod
    def paginate(cls, items: List[T], page: Optional[int] = None, 
                per_page: Optional[int] = None, **kwargs) -> 'Pagination[T]':
        """
        从完整列表创建分页对象
        
        Args:
            items: 完整的项目列表
            page: 请求的页码，如果为None则从请求参数获取
            per_page: 每页数量，如果为None则从请求参数获取
            
        Returns:
            分页对象
        """
        # 从请求参数获取页码和每页数量
        if page is None:
            try:
                page = int(request.args.get('page', 1))
            except (TypeError, ValueError):
                page = 1
        
        if per_page is None:
            try:
                per_page = int(request.args.get('per_page', 20))
            except (TypeError, ValueError):
                per_page = 20
        
        # 验证页码和每页数量
        page = max(1, page)
        per_page = min(max(1, per_page), 100)  # 限制最大每页100条
        
        # 计算偏移量
        start = (page - 1) * per_page
        end = start + per_page
        
        # 截取当前页的项目
        page_items = items[start:end]
        
        return cls(
            items=page_items,
            page=page,
            per_page=per_page,
            total=len(items),
            **kwargs
        )

# 装饰器版本的分页
def paginate(items_getter=None, default_per_page=20, max_per_page=100):
    """
    分页装饰器
    
    Args:
        items_getter: 获取完整列表的函数，如果为None则使用原始响应
        default_per_page: 默认每页数量
        max_per_page: 最大每页数量
        
    Returns:
        装饰器函数
    """
    def decorator(f):
        def wrapper(*args, **kwargs):
            # 获取页码和每页数量
            try:
                page = int(request.args.get('page', 1))
            except (TypeError, ValueError):
                page = 1
            
            try:
                per_page = int(request.args.get('per_page', default_per_page))
            except (TypeError, ValueError):
                per_page = default_per_page
            
            # 验证参数
            page = max(1, page)
            per_page = min(max(1, per_page), max_per_page)
            
            # 调用原始函数
            result = f(*args, **kwargs)
            
            # 处理结果
            if isinstance(result, tuple) and len(result) == 2:
                items, total = result
            elif items_getter:
                items = items_getter(result)
                total = len(items)
            else:
                items = result
                total = len(items)
            
            # 创建分页对象
            pagination = Pagination(
                items=items,
                page=page,
                per_page=per_page,
                total=total
            )
            
            return pagination.to_dict()
        
        # 保留原始函数的元数据
        wrapper.__name__ = f.__name__
        wrapper.__doc__ = f.__doc__
        return wrapper
    
    return decorator